/*
 * @Author: liusheng
 * @Date: 2022-04-28 19:24:57
 * @LastEditors: liusheng
 * @LastEditTime: 2022-04-28 23:12:04
 * @Description: 剑指 Offer II 048. 序列化与反序列化二叉树
 * email:liusheng613@126.com
 * Copyright (c) 2022 by liusheng/liusheng, All Rights Reserved. 
 剑指 Offer II 048. 序列化与反序列化二叉树
序列化是将一个数据结构或者对象转换为连续的比特位的操作，进而可以将转换后的数据存储在一个文件或者内存中，同时也可以通过网络传输到另一个计算机环境，采取相反方式重构得到原数据。

请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑，只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

示例 1：



输入：root = [1,2,3,null,null,4,5]
输出：[1,2,3,null,null,4,5]
示例 2：

输入：root = []
输出：[]
示例 3：

输入：root = [1]
输出：[1]
示例 4：

输入：root = [1,2]
输出：[1,2]
 

提示：

输入输出格式与 LeetCode 目前使用的方式一致，详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式，也可以采用其他的方法解决这个问题。
树中结点数在范围 [0, 104] 内
-1000 <= Node.val <= 1000
 

注意：本题与主站 297 题相同：https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/ 
 */

/*
there is not a well enough solution,need to optimize
*/

#include "header.h"
// Definition for a binary tree node.
struct TreeNode {
    int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode() : val(0), left(nullptr), right(nullptr) {}
      TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
      TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        //-1000 <= Node.val <= 1000,10010 represent null node
        //convient for string int convert
        if (!root)
        {
            return "10010";
        }

        //preorder traverse encode
        string str(to_string(root->val));
        str += "," + serialize(root->left);
        str += "," + serialize(root->right);

        return str;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int n = data.size();

        //construct string list 
        list<string> lstr;
        string str;
        for (int i = 0; i < n; ++i)
        {
            if (data[i] == ',')
            {
                lstr.push_back(str);
                str.clear();
            }
            else
            {
                str.push_back(data[i]);
            }
        }

        return deserializeHelper(lstr);
    }
private:
    //use string list to minimum remove front cost
    TreeNode * deserializeHelper(list<string> & data)
    {
        if (data.empty())
        {
            return nullptr;
        }

        int nodeVal = stoi(data.front());
        // printf("nodeVal:%d\n",nodeVal);
        data.pop_front();

        if (nodeVal != 10010)
        {
            TreeNode * node = new TreeNode(nodeVal);
            node->left = deserializeHelper(data);
            node->right = deserializeHelper(data);

            return node;
        }

        return nullptr; 
    }
};

/*
encode Tree in preorder
decode Tree in preorder
nodeVal split by ',',10010 represent null node
*/
class Codec2 {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if (!root)
        {
            //because -1000 <= Node.val <= 1000
            //out of range value represent null
            return "10010";
        }
        
        string str;
        
        str = to_string(root->val);

        str += "," + serialize(root->left);
        str += "," + serialize(root->right);
     
         
        return str;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int n = data.size();
        string nodeValStr;
        queue<int> qData;
        for (int i = 0; i < n; ++i)
        {
            if (data[i] == ',')
            {
                qData.push(stoi(nodeValStr));
                nodeValStr.clear();
            }
            else
            {
                nodeValStr.push_back(data[i]);
            }
        }
        return deserializeHelper(qData);
    }
private:
    TreeNode *  deserializeHelper(queue<int> & data)
    {
        if (data.empty())
        {
            return nullptr;
        }
        
        int nodeVal = data.front();
        data.pop();
        
        if (nodeVal != 10010)
        {
            TreeNode * node = new TreeNode(nodeVal);
            node->left = deserializeHelper(data);
            node->right = deserializeHelper(data);
            
            return node;
        }
        return nullptr;
    }
};